home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
United Public Domain Gold 4
/
United Public Domain Gold 4.iso
/
fredfish
/
ff.0388.dms
/
ff.0388.adf
/
SnoopDos
/
res.s
< prev
next >
Wrap
Text File
|
1990-10-23
|
7KB
|
137 lines
*:ts=8
*****************************************************************************
* *
* RES.S (C) Copyright Eddy Carroll 1989 *
* *
* This module allows you to make a duplicate copy of your current process. *
* In fact, both processes actually share the same code. However, the *
* seglist pointer of the current process is modified so that when the *
* process terminates, the memory doesn't get freed (if it did, the new *
* process would suddenly find itself deallocated. Hello guru...) *
* This code only works when called from CLI processes. *
* *
* The parameters passed are similar to those for CreateProc(), with the *
* difference that instead of passing a BPTR to a seglist, you pass the *
* address of the function the new process should start executing at. *
* *
* When the new process returns from this function, it will be removed from *
* the system, and its memory (finally) deallocated. *
* *
* The typical use for a function like this is to allow a program to detach *
* itself from a CLI (completely, with no trailing console handles etc.) *
* when it is run. This is a convenient feature for the user, if the program *
* is of the sort designed to sit in the background the whole time, rather *
* than do something immediately, then exit. *
* *
* Lattice provide cback.o which at first glance would seem to provide a *
* similar solution. However, cback.o makes it difficult to print error *
* messages to the console if there is an error on the command line - by *
* the time you spot the error, the CLI prompt has already been printed *
* and your error message is printed after it. This looks very messy. *
* Res avoids this problem by not spawning the background process until *
* after the error checking has been done. *
* *
* From C, you call it as follows: *
* *
* pid = res(name,pri,func,stacksize) *
* *
* name - pointer to null terminated string *
* pri - integer, priority of the new process *
* func - pointer to the function for new process to call *
* stacksize - integer, size of the stack for the new process *
* *
* pid - Process ID of new process, or 0 if none created *
* *
*****************************************************************************
INCLUDE "exec/types.i"
INCLUDE "exec/alerts.i"
INCLUDE "exec/nodes.i"
INCLUDE "exec/lists.i"
INCLUDE "exec/ports.i"
INCLUDE "exec/libraries.i"
INCLUDE "exec/tasks.i"
INCLUDE "libraries/dos.i"
INCLUDE "libraries/dosextens.i"
INCLUDE "workbench/startup.i"
INCLUDE "exec/funcdef.i"
INCLUDE "exec/exec_lib.i"
INCLUDE "libraries/dos_lib.i"
xref _exit
xref _DOSBase
xdef _res
AbsExecBase equ 4
segsize equ 36 ; Size of fake seg. (code = 28 bytes)
csect text,0,0,1,2 * xref's after this are 16-bit reloc
callsys macro
CALLLIB _LVO\1
endm
_res:
movem.l d2-d4/a2/a3/a6,-(a7) ; Save registers
move.l AbsExecBase.w,a6 ; Get base of Exec library
moveq #0,d1 ; Any sort of memory will do
moveq #segsize,d0 ; Get size of fake segment
callsys AllocMem ; Grab some memory
tst.l d0 ; Did we get any?
beq fatal ; If not, abort immediately!
move.l d0,a3 ; Save pointer to memory
sub.l a1,a1 ; NULL pointer indicates our process
callsys FindTask ; Get pointer to our process block
move.l d0,a2 ; Save it
move.l pr_CLI(A2),a0 ; Get BPTR to our process's segarray
add.l a0,a0 ; Convert BPTR to address
add.l a0,a0 ;
move.l cli_Module(a0),4(a3) ; Make fake segment point to our code
clr.l cli_Module(a0) ; Remove process seg. from CLI seglist
move.l #segsize,(a3) ; Set size of fake seglist
lea.l 8(a3),a2 ; Get pointer to first code byte
;
; Now a tiny machine code program is constructed. It looks like this:
;
; move.l #$xxxxxx,A4 ; Initialise A4
; jsr $xxxxxx ; Call user program
; move.l #$xxxxxx,A6 ; Load DOSbase into A6
; move.l #$xxxxxx,d1 ; Get BPTR to this segment
; jmp UnLoadSeg(A6) ; Unload our process from memory
;
; It's built "on the fly" so to speak, to keep code size down, and also
; because it's a convenient way of initialising all the variables.
; Note that a potential problem exists if DOSBase should somehow alter or
; disappear. We'll assume it will remain relatively stable for the next
; few years anyway :-)
;
move.l _DOSBase,a6 ; Prepare for DOS call
move.w #$287C,(a2)+ ; Store MOVE.L $xxxxxx,A4 instruction
move.l a4,(a2)+ ; Output value of A4 to initialise to
move.w #$4EB9,(a2)+ ; Store JSR $xxxxxx
move.l 36(a7),(a2)+ ; followed by address of user function
move.w #$2C7C,(a2)+ ; Store MOVE.L $xxxxxx,A6 instruction
move.l a6,(a2)+ ; followeds by current DOSbase
;
lea 4(a3),a3 ; Now get seglist ptr to fake segment
move.l a3,d3 ; and convert it to BPTR
lsr.l #2,d3 ; D3 now has seglist ptr to fake seg
move.w #$223C,(a2)+ ; Store MOVE.L $xxxxxx,D1 instruction
move.l d3,(a2)+ ; Followed by BPTR to the segment
move.l #$4EEEFF64,(a2)+ ; Store JMP UnLoadSeg(A6)
;
move.l 28(A7),d1 ; Get pointer to name
move.l 32(A7),d2 ; Get process priority
move.l 40(A7),d4 ; Get stacksize
callsys CreateProc ; Create new process
movem.l (a7)+,d2-d4/a2/a3/a6 ; Pop registers
rts ; Return
fatal:
moveq #120,d0 ; Set error exit code
jmp _exit ; And exit
end